TerraformでDNSレコード,ACM証明書,ALBをプロビジョニングする際に入れておいたほうが良いコード
状況
ALBがフロントにあるWebアプリケーションです。https通信のためにACM証明書を作りALBにアタッチします。またクライアントがアクセスするFQDNに対応するDNSレコードはRoute53ホストゾーンに作成します。これらをすべてTerraformでプロビジョニングします。
こういった状況において、Terraformのコードに2点加えておいたほうがいいものがあることがわかりましたのでレポートします。
なお、ベースとなるコードは以下のエントリのものです。
TerraformとAWS Providerのバージョンは以下です。
- Terraform: 0.14.9
- AWS Provider: 3.31.0
1. aws_acm_certificateにcreate_before_destroyを入れる
以下のように、aws_acm_certificate
リソースにlifecycle
ブロックを作ってcreate_before_destroy = true
を書きます。
resource "aws_acm_certificate" sample" { domain_name = data.aws_ssm_parameter.fqdn.value validation_method = "DNS" lifecycle { create_before_destroy = true } }
これを入れておかないと、FQDN値を変更した際に問題になりました。
DNSレコードを変更してterraform apply
すると、aws_acm_certificate
の再作成(削除→作成)が走ります。ですがその削除がいつまで立っても終わりませんでした。
module.base.aws_route53_record.hostname: Creating... module.base.aws_route53_record.cert_validation["hoge.example.com"]: Destruction complete after 31s module.base.aws_acm_certificate.sample: Destroying... [id=arn:aws:acm:ap-northeast-1:123456789012:certificate/ac0c0614-1f1e-490b-9748-eb6491c4c922] module.base.aws_route53_record.hostname: Still creating... [10s elapsed] module.base.aws_acm_certificate.sample: Still destroying... [id=arn:aws:acm:ap-northeast-1:123456789012...e/ac0c0614-1f1e-490b-9748-eb6491c4c922, 10s elapsed] module.base.aws_route53_record.hostname: Still creating... [20s elapsed] module.base.aws_acm_certificate.sample: Still destroying... [id=arn:aws:acm:ap-northeast-1:123456789012...e/ac0c0614-1f1e-490b-9748-eb6491c4c922, 20s elapsed] module.base.aws_route53_record.hostname: Still creating... [30s elapsed] module.base.aws_acm_certificate.sample: Still destroying... [id=arn:aws:acm:ap-northeast-1:123456789012...e/ac0c0614-1f1e-490b-9748-eb6491c4c922, 30s elapsed] module.base.aws_route53_record.hostname: Creation complete after 31s [id=Z0848872OXCSAFSLG4OP_hoge.example.com_A] module.base.aws_acm_certificate.sample: Still destroying... [id=arn:aws:acm:ap-northeast-1:123456789012...e/ac0c0614-1f1e-490b-9748-eb6491c4c922, 40s elapsed] module.base.aws_acm_certificate.sample: Still destroying... [id=arn:aws:acm:ap-northeast-1:123456789012...e/ac0c0614-1f1e-490b-9748-eb6491c4c922, 50s elapsed] module.base.aws_acm_certificate.sample: Still destroying... [id=arn:aws:acm:ap-northeast-1:123456789012...e/ac0c0614-1f1e-490b-9748-eb6491c4c922, 1m0s elapsed] module.base.aws_acm_certificate.sample: Still destroying... [id=arn:aws:acm:ap-northeast-1:123456789012...e/ac0c0614-1f1e-490b-9748-eb6491c4c922, 1m10s elapsed] module.base.aws_acm_certificate.sample: Still destroying... [id=arn:aws:acm:ap-northeast-1:123456789012...e/ac0c0614-1f1e-490b-9748-eb6491c4c922, 1m20s elapsed] module.base.aws_acm_certificate.sample: Still destroying... [id=arn:aws:acm:ap-northeast-1:123456789012...e/ac0c0614-1f1e-490b-9748-eb6491c4c922, 1m30s elapsed] module.base.aws_acm_certificate.sample: Still destroying... [id=arn:aws:acm:ap-northeast-1:123456789012...e/ac0c0614-1f1e-490b-9748-eb6491c4c922, 1m40s elapsed] module.base.aws_acm_certificate.sample: Still destroying... [id=arn:aws:acm:ap-northeast-1:123456789012...e/ac0c0614-1f1e-490b-9748-eb6491c4c922, 1m50s elapsed] module.base.aws_acm_certificate.sample: Still destroying... [id=arn:aws:acm:ap-northeast-1:123456789012...e/ac0c0614-1f1e-490b-9748-eb6491c4c922, 2m0s elapsed] module.base.aws_acm_certificate.sample: Still destroying... [id=arn:aws:acm:ap-northeast-1:123456789012...e/ac0c0614-1f1e-490b-9748-eb6491c4c922, 2m10s elapsed] module.base.aws_acm_certificate.sample: Still destroying... [id=arn:aws:acm:ap-northeast-1:123456789012...e/ac0c0614-1f1e-490b-9748-eb6491c4c922, 2m20s elapsed] module.base.aws_acm_certificate.sample: Still destroying... [id=arn:aws:acm:ap-northeast-1:123456789012...e/ac0c0614-1f1e-490b-9748-eb6491c4c922, 2m30s elapsed] module.base.aws_acm_certificate.sample: Still destroying... [id=arn:aws:acm:ap-northeast-1:123456789012...e/ac0c0614-1f1e-490b-9748-eb6491c4c922, 2m40s elapsed] module.base.aws_acm_certificate.sample: Still destroying... [id=arn:aws:acm:ap-northeast-1:123456789012...e/ac0c0614-1f1e-490b-9748-eb6491c4c922, 2m50s elapsed] module.base.aws_acm_certificate.sample: Still destroying... [id=arn:aws:acm:ap-northeast-1:123456789012...e/ac0c0614-1f1e-490b-9748-eb6491c4c922, 3m0s elapsed] module.base.aws_acm_certificate.sample: Still destroying... [id=arn:aws:acm:ap-northeast-1:123456789012...e/ac0c0614-1f1e-490b-9748-eb6491c4c922, 3m10s elapsed] module.base.aws_acm_certificate.sample: Still destroying... [id=arn:aws:acm:ap-northeast-1:123456789012...e/ac0c0614-1f1e-490b-9748-eb6491c4c922, 3m20s elapsed] module.base.aws_acm_certificate.sample: Still destroying... [id=arn:aws:acm:ap-northeast-1:123456789012...e/ac0c0614-1f1e-490b-9748-eb6491c4c922, 3m30s elapsed] module.base.aws_acm_certificate.sample: Still destroying... [id=arn:aws:acm:ap-northeast-1:123456789012...e/ac0c0614-1f1e-490b-9748-eb6491c4c922, 3m40s elapsed] (ずっと続いたので中断しました)
削除が完了しなかった理由ですが、該当aws_acm_certificate
はaws_alb_listener
にて参照されている、つまりACM証明書がALBにアタッチされている状態なので、削除できなかった、という事だと考えられます。
そこで、create_before_destroy = true
を入れることで、
- 新しいFQDNのACM証明書が作成される
- ALBにアタッチされるACM証明書が旧から新に変わる
- 旧ACM証明書が削除される
という実行順序になり、3の時点では旧ACM証明書はALBへのアタッチが解除済なので削除可能になります。
2. aws_alb_listenerにdepends_onを入れる
aws_alb_listener
にdepends_on
argumentを指定して、値にaws_acm_certificate_validation
を入れます。
resource "aws_alb_listener" "https" { load_balancer_arn = aws_alb.sample.arn port = 443 protocol = "HTTPS" ssl_policy = "ELBSecurityPolicy-TLS-1-2-Ext-2018-06" certificate_arn = aws_acm_certificate.sample.arn default_action { type = "forward" target_group_arn = aws_alb_target_group.sample.arn } depends_on = [ aws_acm_certificate_validation.sample ] }
これを入れておかないと、これもFQDN値を変更した際にエラーになりました。
Error: Error modifying LB Listener: UnsupportedCertificate: The certificate 'arn:aws:acm:ap-northeast-1:123456789012:certificate/a5051cc8-d500-4eca-981c-b7fbc9bf4234' must have a fully-qualified domain name, a supported signature, and a supported key size. status code: 400, request id: 4d70d132-7224-4ef8-b26e-bd7511244f20 on ../../modules/base/alb.tf line 28, in resource "aws_alb_listener" "https": 28: resource "aws_alb_listener" "https" {
aws_acm_certificate_validation
は、作ったACM証明書と、そのvalidation用に作ったDNSレコードを紐付けるリソースです。(前提としてACM証明書の検証方法としてDNS検証を選択しています。)検証完了=このリソース作成完了になります。
depends_on
を入れておかないと、aws_acm_certificate_validation
再作成完了前にaws_alb_listener
の変更、つまりACM証明書の旧→新への付け直しが始まっています。検証完了前のACM証明書がALBに紐付けられることになります。そのためError modifying LB Listener: UnsupportedCertificate:
というエラーが出たと考えられます。
module.base.aws_alb_listener.https: Modifying... [id=arn:aws:elasticloadbalancing:ap-northeast-1:123456789012:listener/app/sample-alb/15bc65f1258f01da/740d21f9c91f2e8f] module.base.aws_route53_record.hostname: Still destroying... [id=Z0848872OXCSAFSLG4OP_hoge.example.com_A, 10s elapsed] module.base.aws_route53_record.cert_validation["hoge.example.com"]: Still destroying... [id=Z0848872OXCSAFSLG4OP__86b98a079a13baf96...7b.hoge.example.com._CNAME, 10s elapsed] module.base.aws_route53_record.cert_validation["fuga.example.com"]: Still creating... [10s elapsed] module.base.aws_route53_record.hostname: Still destroying... [id=Z0848872OXCSAFSLG4OP_hoge.example.com_A, 20s elapsed] module.base.aws_route53_record.cert_validation["hoge.example.com"]: Still destroying... [id=Z0848872OXCSAFSLG4OP__86b98a079a13baf96...7b.hoge.example.com._CNAME, 20s elapsed] module.base.aws_route53_record.cert_validation["fuga.example.com"]: Still creating... [20s elapsed] module.base.aws_route53_record.hostname: Still destroying... [id=Z0848872OXCSAFSLG4OP_hoge.example.com_A, 30s elapsed] module.base.aws_route53_record.cert_validation["hoge.example.com"]: Still destroying... [id=Z0848872OXCSAFSLG4OP__86b98a079a13baf96...7b.hoge.example.com._CNAME, 30s elapsed] module.base.aws_route53_record.hostname: Destruction complete after 31s module.base.aws_route53_record.hostname: Creating... module.base.aws_route53_record.cert_validation["hoge.example.com"]: Destruction complete after 30s module.base.aws_route53_record.cert_validation["fuga.example.com"]: Still creating... [30s elapsed] module.base.aws_route53_record.cert_validation["fuga.example.com"]: Creation complete after 31s [id=Z0848872OXCSAFSLG4OP__e0dc1d1c745acf92b971a7253f915766.fuga.example.com._CNAME] module.base.aws_acm_certificate_validation.sample: Creating... module.base.aws_route53_record.hostname: Still creating... [10s elapsed] module.base.aws_acm_certificate_validation.sample: Creation complete after 2s [id=2022-02-03 09:15:27.466 +0000 UTC] module.base.aws_route53_record.hostname: Still creating... [20s elapsed] module.base.aws_route53_record.hostname: Still creating... [30s elapsed] module.base.aws_route53_record.hostname: Creation complete after 30s [id=Z0848872OXCSAFSLG4OP_fuga.example.com_A] Error: Error modifying LB Listener: UnsupportedCertificate: The certificate 'arn:aws:acm:ap-northeast-1:123456789012:certificate/a5051cc8-d500-4eca-981c-b7fbc9bf4234' must have a fully-qualified domain name, a supported signature, and a supported key size. status code: 400, request id: 4d70d132-7224-4ef8-b26e-bd7511244f20 on ../../modules/base/alb.tf line 28, in resource "aws_alb_listener" "https": 28: resource "aws_alb_listener" "https" {
depends_on
を入れると、aws_acm_certificate_validation
再作成完了を待ってからaws_alb_listener
の変更=ACM証明書の旧→新への付け直しが始まるので、前述のエラーを回避できます。
module.base.aws_route53_record.cert_validation["fuga.example.com"]: Still creating... [30s elapsed] module.base.aws_route53_record.cert_validation["fuga.example.com"]: Creation complete after 31s [id=Z0848872OXCSAFSLG4OP__86b98a079a13baf96eca4c9b185a497b.fuga.example.com._CNAME] module.base.aws_acm_certificate_validation.sample: Creating... module.base.aws_route53_record.hostname: Still creating... [10s elapsed] module.base.aws_acm_certificate_validation.sample: Creation complete after 2s [id=2022-02-03 09:51:53.476 +0000 UTC] module.base.aws_alb_listener.https: Modifying... [id=arn:aws:elasticloadbalancing:ap-northeast-1:123456789012:listener/app/sample-alb/15bc65f1258f01da/740d21f9c91f2e8f] module.base.aws_alb_listener.https: Modifications complete after 1s [id=arn:aws:elasticloadbalancing:ap-northeast-1:123456789012:listener/app/sample-alb/15bc65f1258f01da/740d21f9c91f2e8f] module.base.aws_acm_certificate.sample: Destroying... [id=arn:aws:acm:ap-northeast-1:123456789012:certificate/15051cc8-d500-4eca-981c-b7fbc9bf4234] module.base.aws_acm_certificate.sample: Destroying... [id=arn:aws:acm:ap-northeast-1:123456789012:certificate/84181cfd-7c19-424f-a6fe-0a9fa21881e1]
今回ALBのケースしか検証していませんが、CloudFrontにACM証明書を紐付ける場合も同様のことが起きるのではないかと思います。